//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// 'File|Save' and 'File|Save As...' commands.
//

# include "StdAfx.h"
# include "Resource.h"
# include "UndoRedo.h"
# include "Map.h"
# include "Save.h"
# include "Log.h"
# include "Menu.h"
# include "Status.h"
# include "RecentFiles.h"
# include "File.h"
# include "fast_floor.h"
# include "Globals.h"

bool CanSave () {
	return g_bModified && g_pSaverInfo && (g_pSaverInfo->m_dwFlags & ftiImportExport) == 0 && g_strFileName [0];
}

bool RequestSave () {
	if (g_bModified) {
		switch (::MessageBox (g_hWnd, "The map is modified.\nDo you want to save it?", "Save", MB_YESNOCANCEL | MB_ICONQUESTION)) {
			case IDYES:
				if (g_pSaverInfo && (g_pSaverInfo->m_dwFlags & ftiImportExport) == 0 && g_strFileName [0])
					SaveMap ();
				else
					SaveMapAs ();
				return true;
			case IDNO:     return true;
			case IDCANCEL: return false;
		}
	}
	return true;
}

void SaveMapAs () {
	CFileTypeInfo::ShowSaveFile ();
}

void SaveMap () { 
	SaveMap (g_pSaverInfo, g_strFileName);
}

void SaveMap (const CFileTypeInfo * _pSaverInfo, const char * _strFileName) {
	assert (_pSaverInfo);
	std::auto_ptr<CMapSaver> pSaver = std::auto_ptr<CMapSaver> (_pSaverInfo->m_pfCreateSaver ());

	CCritSec::CLock lock (g_cs);

	SetStatus (GetStr (IDS_STATUS_PREPARE_SAVING));
	SetProgressStatus (0);
	if (! pSaver->PrepareToSave (g_map)) {
		SetStatusReady ();
		return;
	}

	// Rename old file to .BAK.
	char strBakFile [MAX_PATH];
	bool bHaveBakFile = false;
	if (DoesFileExist (_strFileName)) {
		CreateUniqueFileName (_strFileName, "BAK", strBakFile);
		::MoveFile (_strFileName, strBakFile);
		bHaveBakFile = true;
	}

	CWaiter w;

	const long lStartTime = ::GetTickCount ();

	//
	// Open the file.
	//

	CFileForWrite hFile (_strFileName);
	if (! hFile.IsValid ()) {
		ErrorMsgBox ("Can't open file\n%s.", _strFileName);
		SetStatusReady ();
		return;
	}

	//
	// Save the map.
	//

	ClearLog ();
	ReportText ("Saving map to file '%s'...", _strFileName);

	SetStatus (GetStr (IDS_STATUS_SAVING));

	bool bSaveOK = false;
	try {
		bSaveOK = pSaver->Save (hFile, _strFileName, g_map);
	} catch (const COutOfMemory & _oom) {
		_oom.Report ();
	} catch (const std::exception & _e) {
		ErrorMsgBox ("Unhandled exception: %s.", _e.what ());
	}
	pSaver = std::auto_ptr<CMapSaver> (NULL);

	if (! bSaveOK) {
		ErrorMsgBox ("Saving has failed.");
		SetStatusReady ();

		hFile.Close ();
		::DeleteFile (_strFileName);

		return;
	}

	//
	// Report about results.
	//

	if (GetWarningsCount ())
		ReportText ("%d warning(s).", GetWarningsCount ());

	char strTime [64];
	::sprintf (strTime, "Save time %0.2f s", .001*(::GetTickCount () - lStartTime));
	ReportText (strTime);

	// Delete BAK file.
	if (bHaveBakFile)
		::DeleteFile (strBakFile);

	//
	// Update GUI elements.
	//

	AddRecentFile (_strFileName);

	ResetUndoRedo ();
	g_bModified = false;

	g_pSaverInfo = _pSaverInfo;
	::strncpy (g_strFileName, _strFileName, MAX_PATH);
	UpdateTitle ();

	UpdateMenu ();

	SetStatusReady ();
}

bool CheckVectorData (const map_t & _map) {
	CCritSec::CLock lock (g_cs);

	bool bThereAreVectorData = false;
	for (size_t cKind = 0; cKind < rkMax; ++ cKind) {
		const layer_t & layer = _map.layers [cKind];
		const rgns_t & rgns = layer.rgns;
		for (rgns_t::const_iterator iRgn = rgns.begin (); iRgn != rgns.end (); ++ iRgn) {
			const rgn_t & rgn = * iRgn;
			if (rgn.IsDeleted () || rgn.IsWTR ())
				continue;

			bThereAreVectorData = true;
		}
	}
	if (! bThereAreVectorData) {
		ErrorMsgBox (
			"There are no vector data to export.\n"
			"\n"
			"NOTE: raster maps should be vectorized before loading to GPS receiver,\n"
			"and tracks and waypoints should be converted to map objects."
		);
		return false;
	}

	if (g_map.bNoHeader || g_map.Levels.empty ()) {
		ErrorMsgBox (
			"The map has no header data or zoom levels.\n"
			"Please check settings in 'File | Map Properties'."
		);
		return false;
	}

	return true;
}
